package CCRMClient.Controllers;

import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import Common.SERVER_COMMANDS;
import Common.ServerRequest;
import Common.Entities.Category;
import Common.Entities.CustomerResponse;
import Common.Entities.Product;
import Common.Entities.ProductPicture;
import Common.Entities.STATUS;
import Common.Entities.Type;

/**
 * This class implements all use cases regarding catalog items
 * @author Ori Ziv
 *
 */
public class CatalogManager {
	
	/**
	 * This method create a server request to add a new product category to the DB.
	 * @param catName - category name
	 * @param catDescription - category description (can be null)
	 * @return - server request with command: ADD_CATEGORY and the new category object to insert
	 */
	public static ServerRequest addCategory (String catName, String catDescription) {
		Category cat = new Category (catName, catName, catDescription);
		return new ServerRequest (SERVER_COMMANDS.ADD_CATEGORY, null, cat);
	}

	/**
	 * This method set server request to search a category
	 * @param catName - category name
	 * @return
	 */
	public static ServerRequest searchCategory(String catName) {
		Category cat = new Category (catName, catName);
		return new ServerRequest (SERVER_COMMANDS.GET_CATEGORY_TYPES, null, cat);
	}

	/**
	 * This method set server request to add a new type to a category
	 * @param typeName - new type to add
	 * @param categoryName - the category the type belongs to
	 * @return
	 */
	public static ServerRequest addType(String typeName, String categoryName) {
		Type newType = new Type (null, typeName, categoryName);
		return new ServerRequest (SERVER_COMMANDS.ADD_TYPE, null, newType);
	}

	/**
	 * This method create a server request to add a new product to the DB
	 * @param productName - new product's name
	 * @param productDescription - new product's description
	 * @param productBasePrice - new product's base price
	 * @param picturePath - new product's picture absolute path
	 * @param pictureTitle - new product's picture title
	 * @return - ServerRequest with relevant server command and a product entity
	 */
	public static ServerRequest addProduct(String productName,
			String productDescription, float productBasePrice, String picturePath, String pictureTitle) {
		Product product = new Product (-1, productName, productDescription,
				productBasePrice, STATUS.ACTIVE);
		product.setPicture(addProductPicture(picturePath, pictureTitle, "-1"));
		return new ServerRequest (SERVER_COMMANDS.ADD_PRODUCT, null, product);
	}

	/**
	 * This method convert a file into a matrix of bytes and pack it in a ServerRequest
	 * 
	 * @param picturePath - absolute path to the file
	 * @param pictureTitle - file title
	 * @param productID - picture's product ID
	 * @return - ServerRequest with ADD_PRODUCT_PICTURE command and the file represented as a matrix of bytes
	 */
	public static ProductPicture addProductPicture(String picturePath, String pictureTitle, String productID) {
		try {
			File picFile = new File (picturePath);
			FileInputStream picIS = new FileInputStream(picFile);
			BufferedInputStream picIBuf = new BufferedInputStream(picIS);
			ProductPicture picture = new ProductPicture(productID, pictureTitle, picturePath, (int)picFile.length());
			
			picIBuf.read(picture.getPicture(), 0, (int) picFile.length());
			
			picIBuf.close();
			picIS.close();
			return picture;
		} catch (IOException e) {
			return null;
		}		
	}

	/**
	 * This method create a server request to search a product in the DB by a search string
	 * @param search - search string
	 * @return - ServerRequest with relevant command and search string
	 */
	public static ServerRequest searchProduct(SERVER_COMMANDS command, String search) {
		return new ServerRequest (command, null, search);
	}

	/**
	 * This method create a server request to get product details from the DB by product ID
	 * @param productID - product ID
	 * @return - ServerRequest with relevant command and productID integer
	 */
	public static ServerRequest getProduct(long productID) {
		return new ServerRequest(SERVER_COMMANDS.GET_PRODUCT, null, new Long(productID));
	}

	/**
	 * This method receive a product picture and convert it to a file 
	 * @param picture - product picture to convert
	 * @return File descriptor of the saved picture or null in case of error
	 */
	public static File downloadPicture(ProductPicture picture) {
		if (picture == null) return null;
		
		File picDir = new File ("Client_Products_Pictures");
		if (!picDir.exists()) {
			try {
				picDir.mkdir();
			} catch (SecurityException e) {
				return null;
			}
		}
		try {
			File picFile = new File(picDir, picture.getPictureName());
			FileOutputStream picOutStrm = new FileOutputStream (picFile);
			picOutStrm.write(picture.picture, 0, picture.picture.length);
			picOutStrm.close();
			return picFile;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * This method create a server request to set product status
	 * @param productStatus - product status to be set
	 * @param productID - product ID
	 * @return - ServerRequest with relevant command and an Object array of the productID (Long) and the new status (STATUS)
	 */
	public static ServerRequest setProductStatus(STATUS productStatus, long productID) {
		Object entity[] = new Object[2];
		entity[0] = new Long(productID);
		entity[1] = productStatus;
		return new ServerRequest(SERVER_COMMANDS.UPDATE_PRODUCT_STATUS, null, entity);
	}

	/**
	 * This method create a server request to update an existing product entity data in the DB
	 * @param product - product object with new product data
	 * @return - a server request
	 */
	public static ServerRequest updateProduct(Product product) {
		return new ServerRequest (SERVER_COMMANDS.UPDATE_PRODUCT, null, product);
	}
	/**
	 * This method create a server request to show the product's details in the sale for adding it to the cart.
	 * 
	 */
	public static ServerRequest showProductInSale(CustomerResponse response){
		return new ServerRequest (SERVER_COMMANDS.SHOW_PRODUCT_IN_SALE, null, response);
	}
}
